use super::datastruct::{PushData,TXACK,PullResp};
use std::net::UdpSocket;
use serde_json::to_string;
use dashmap::DashMap;
use std::sync::Arc;
use rand::Rng;

// 保存发送的 pull_resp 的 token
lazy_static::lazy_static! {
    static ref SENT_PULL_RESP_TOKENS: Arc<DashMap<[u8; 2], String>> = Arc::new(DashMap::new());
}

/**
 * 根据第四个字节identifier 判断是什么类型的网关请求
 * 六种请求其中 push_data pull_data tx_ack是网关发送至服务器的 接收请求
 * 其中push_ack PULL_RESP PULL_ACK 是服务器发送给网关的
 * 
 * @param data: &[u8] - 接收到的LoRa数据包
 * @param socket: &UdpSocket - UDP套接字
 * @param dest_addr: &str - 目标地址
 * @return Result<(), String> - 操作成功返回Ok(())，失败返回Err(消息)
 */
pub fn handle_lora_data(data: &[u8], socket: &UdpSocket, dest_addr: &str) -> Result<(), String> {
    if data.len() < 4 {
        return Err("LoRa 数据长度不足".to_string());
    }
    match data[3] {
        0x00 => {
            let _res = push_data(data);
            if let Err(e) = _res {
                println!("push_data 错误: {}", e);
                return Err(e);
            }
            let _up = push_ack(data, socket, dest_addr);
            if let Err(e) = _up {
                println!("push_ack 错误: {}", e);
                return Err(e);
            }
        }
        0x02 => {
            let _res = pull_data(data);
            if let Err(e) = _res {
                println!("pull_data 错误: {}", e);
                return Err(e);
            }
            let _down = pull_ack(data, socket, dest_addr);
            if let Err(e) = _down {
                println!("pull_ack 错误: {}", e);
                return Err(e);
            }
        }
        0x05 => {
            let _res = tx_ack(data);
            if let Err(e) = _res {
                println!("handle_tx_ack 错误: {}", e);
                return Err(e);
            }
        }
        _ => {
            println!("第三位不在预期范围内{}", data[3]);
            return Err("第三位不在预期范围内".to_string());
        }
    }
    Ok(())
}

/**
 * 处理 PUSH_DATA 包
 * 
 * @param data: &[u8] - 接收到的 PUSH_DATA 数据包
 * @return Result<PushData, String> - 操作成功返回Ok(PushData)，失败返回Err(消息)
 */
fn push_data(data: &[u8]) -> Result<PushData, String> {
    let mac: &[u8] = &data[4..12];
    println!("MAC 地址: {:?}", mac);
    let json_data = std::str::from_utf8(&data[12..]).map_err(|_| "无法解析 JSON 数据".to_string())?;
    println!("JSON 数据: {}", json_data);
    serde_json::from_str::<PushData>(json_data).map_err(|_| "JSON 数据格式不正确".to_string())
}

/**
 * 发送 PUSH_ACK 包
 * 
 * @param data: &[u8] - 接收到的 PUSH_DATA 数据包
 * @param socket: &UdpSocket - UDP套接字
 * @param dest_addr: &str - 目标地址
 * @return Result<(), String> - 操作成功返回Ok(())，失败返回Err(消息)
 */
fn push_ack(data: &[u8], socket: &UdpSocket, dest_addr: &str) -> Result<(), String> {
    let token: &[u8] = &data[1..3];
    let mac: &[u8] = &data[4..12];
    println!("MAC 地址: {:?}", mac);

    let mut ack_data: Vec<u8> = Vec::new();
    ack_data.push(data[0]); // protocol version
    ack_data.extend_from_slice(token);
    ack_data.push(0x01); // PUSH_ACK identifier

    socket.send_to(&ack_data, dest_addr).map(|_| ()).map_err(|e| format!("发送 ACK 消息失败: {}", e))
}

/**
 * 处理 PULL_DATA 包
 * 
 * @param data: &[u8] - 接收到的 PULL_DATA 数据包
 * @return Result<(), String> - 操作成功返回Ok(())，失败返回Err(消息)
 */
fn pull_data(data: &[u8]) -> Result<(), String> {
    let mac: &[u8] = &data[4..12];
    println!("MAC 地址: {:?}", mac);
    let token: &[u8] = &data[1..3];
    println!("token: {:?}", token);
    Ok(())
}

/**
 * 发送 PULL_RESP 包
 * 
 * @param data: PullResp - 要发送的 PULL_RESP 数据
 * @param socket: &UdpSocket - UDP套接字
 * @param dest_addr: &str - 目标地址
 * @return Result<(), String> - 操作成功返回Ok(())，失败返回Err(消息)
 */
fn pull_resp(data: PullResp, socket: &UdpSocket, dest_addr: &str) -> Result<(), String> {
    let protocol_version = 2u8; // 协议版本
    let random_token: [u8; 2] = rand::thread_rng().gen(); // 生成随机令牌
    let pull_resp_identifier = 0x03u8; // PULL_RESP标识符

    let json_data = to_string(&data).map_err(|_| "JSON序列化失败".to_string())?;
    let mut packet: Vec<u8> = vec![protocol_version];
    packet.extend_from_slice(&random_token);
    packet.push(pull_resp_identifier);
    packet.extend_from_slice(json_data.as_bytes());

    SENT_PULL_RESP_TOKENS.insert(random_token, dest_addr.to_string());

    socket.send_to(&packet, dest_addr).map(|_| ()).map_err(|_| "发送失败".to_string())
}

/**
 * 发送 PULL_ACK 包
 * 
 * @param data: &[u8] - 接收到的 PULL_DATA 数据包
 * @param socket: &UdpSocket - UDP套接字
 * @param dest_addr: &str - 目标地址
 * @return Result<(), String> - 操作
*/
fn pull_ack(data: &[u8], socket: &UdpSocket, dest_addr: &str) -> Result<String, String> {
    println!("处理 PULL_ACK 数据: {:?}", data);
    // 获取 token和固定的protocol version = 2
    let token: &[u8] = &data[0..3];
    // 获取 MAC 地址
    let mac: &[u8] = &data[4..12];
    println!("MAC 地址: {:?}", mac);

    // 构建 ACK 消息
    let mut ack_data: Vec<u8> = Vec::new();
    ack_data.extend_from_slice(token);
    ack_data.push(0x04); // 根据协议构建具体 ACK 数据

    match socket.send_to(&ack_data, dest_addr) {
        Ok(_) => {
            println!("发送 pull_ack 消息成功{:?}",ack_data);
            Ok("成功".to_string())
        }
        Err(e) => {
            println!("发送 pull_ack 消息失败: {}", e);
            Err("发送 ACK 消息失败".to_string())
        }
    }
}


/**
 * 处理 TX_ACK 包
 * 
 * @param data: &[u8] - 接收到的 PULL_DATA 数据包
 * @param socket: &UdpSocket - UDP套接字
 * @param dest_addr: &str - 目标地址
 * @return Result<(), String> - 操作
*/
fn tx_ack(data: &[u8]) -> Result<String, String> {
    // 获取 token
    let token: [u8; 2] = [data[1], data[2]];
    // 获取 MAC 地址
    let mac: &[u8] = &data[4..12];
    println!("MAC 地址: {:?}", mac);

    // 获取 JSON 数据
    let json_data = std::str::from_utf8(&data[12..]).map_err(|_| "无法解析 JSON 数据".to_string())?;
    println!("JSON 数据: {}", json_data);

    // 解析 JSON 数据
    let tx_ack: TXACK = serde_json::from_str(json_data).map_err(|_| "JSON 数据格式不正确".to_string())?;

    // 验证 token
    if SENT_PULL_RESP_TOKENS.contains_key(&token) {
        println!("验证成功，token 匹配: {:?}", token);
        Ok("成功".to_string())
    } else {
        Err("token 不匹配".to_string())
    }
}
